﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TSharp.Core.Authorization.Resources;
using TSharp.Core.Repository;

namespace TSharp.Core.Authorization.Control.Impl
{
    /// <summary>
    /// 权限实现类
    /// </summary>
    public class ControlManagerImpl : IControlManager
    {
        /// <summary>
        /// The control manager DAO
        /// </summary>
        protected IControlManagerDao ControlManagerDao
        {
            get
            {
                return fac.Value;
            }
        }
        private Lazy<IControlManagerDao> fac = new Lazy<IControlManagerDao>(Osgi.LazyLoading.New<IControlManagerDao>);
        /// <summary>
        /// 资源类别
        /// </summary>
        private ResourceCategory category;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ControlManagerImpl(ResourceCategory resourceCategory)
        {
            this.category = resourceCategory;
        }


        /// <summary>
        /// 获取指定参与者相关的所有资源的操作权限列表
        /// </summary>
        public List<ResourcePermissionKeyValue> GetControlDatasByActor(Guid actorId)
        {
            return ControlManagerDao.GetControlDatasByActor(this.category.code, actorId);
        }

        /// <summary>
        /// 获取所有参与者对指定资源的操作权限列表，对初始化的资源类别有效
        /// </summary>
        public List<ResourcePermissionKeyValue> GetControlDatasByResource(Guid resourceId)
        {
            return ControlManagerDao.GetControlDatasByResource(this.category.code, resourceId);
        }

        /// <summary>
        /// 获取多个参与者对多个资源或者多个资源组的操作权限列表
        /// </summary>
        public void GetControlDatas(List<Guid> actorsId, List<Guid> resourcesId, List<int> operationsCode)
        {
            ControlManagerDao.GetControlDatas(this.category.code, actorsId, resourcesId, operationsCode);
        }

        /// <summary>
        /// 获取多个参与者拥有指定操作权限的资源或者资源组代码列表
        /// </summary>
        public List<Guid> GetAllowActResources(List<Guid> actorsId, int operationCode)
        {
            return ControlManagerDao.GetAllowActResources(this.category.code, actorsId, operationCode);
        }

        /// <summary>
        /// 获取多个参与者禁止指定操作权限的资源或者资源组代码列表
        /// </summary>
        public void GetForbidActResources(List<Guid> actorsId, int operationCode, List<Guid> resourcesId)
        {
            ControlManagerDao.GetForbidActResources(this.category.code, actorsId, operationCode, resourcesId);
        }


        /// <summary>
        /// 删除指定参与者对指定资源的权限
        /// </summary>
        public bool RemoveControlData(Guid actorId, Guid resourceId)
        {
            return ControlManagerDao.RemoveControlData(this.category.code, actorId, resourceId);
        }

        /// <summary>
        /// 删除指定参与者的所有权限
        /// </summary>
        public bool RemoveActorControlDatas(Guid actorId)
        {
            return ControlManagerDao.RemoveActorControlDatas(this.category.code, actorId);
        }

        /// <summary>
        /// 删除指定资源的所有权限
        /// </summary>
        public bool RemoveResourceControlDatas(Guid resourceId)
        {
            return ControlManagerDao.RemoveResourceControlDatas(this.category.code, resourceId);
        }

        /// <summary>
        /// 合并权码，用于数据库存储
        /// </summary>
        /// <param name="permissionIdArray">The permission id array.</param>
        /// <returns>System.Int32.</returns>
        private static int CombinePermissionCode(params int[] permissionIdArray)
        {
            if (permissionIdArray == null || permissionIdArray.Length == 0)
            {
                return 0;
            }

            var bitArray = new BitArray(32);
            var intByBitArray = new int[1];
            foreach (var permissionCode in permissionIdArray)
            {
                bitArray.Set(permissionCode, true);
            }
            bitArray.CopyTo(intByBitArray, 0);
            return intByBitArray[0];
        }

        /// <summary>
        /// 拆分权码，用于权限编辑
        /// </summary>
        private int[] SplitPermissionCode(int permissionCode)
        {
            var bitArray = new BitArray(new[] { permissionCode });
            return this.category.OperationSet.operations
                       .Where(x => bitArray.Length > x.id && bitArray.Get(x.id)).Select(x => x.id).ToArray();
        }

        int[] IControlManager.GetControlData(Guid actorId, Guid resourceId)
        {
            int inheritedMask = CombinePermissionCode(OperationSet.InheritedOperation);
            int code = 0;
            var d = GetOriginControlData(actorId, resourceId);
            if (d.HasValue)
            {
                code = code | d.Value;
            }
            else
                //数据库未存储，默认为继承
                code = inheritedMask;
            return SplitPermissionCode(code);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="actorId"></param>
        /// <param name="resourceId"></param>
        /// <param name="getInheritedOnly"></param>
        /// <returns></returns>
        public int[] GetControlData(Guid actorId, Guid resourceId, bool getInheritedOnly)
        {
            int inheritedMask = CombinePermissionCode(OperationSet.InheritedOperation);
            int code = 0;
            if (!getInheritedOnly)
            {
                var d = GetOriginControlData(actorId, resourceId);
                if (d.HasValue)
                {
                    code = code | d.Value;
                    //
                    if ((code & inheritedMask) != inheritedMask)
                    {
                        //如果存储的标识中指定不继承，则直接返回
                        return SplitPermissionCode(code);
                    }
                }
                else
                    //数据库未存储，默认为继承
                    code = inheritedMask;
            }
            var parentresource = category.GetParentResource(actorId, resourceId);
            while (parentresource != null)
            {
                var parentCode = GetOriginControlData(actorId, parentresource.Id);
                if (parentCode.HasValue)
                {
                    code = code | (parentCode.Value & ~inheritedMask);
                }
                parentresource = category.GetParentResource(actorId, parentresource.Id);
            }

            return SplitPermissionCode(code);
        }

        private int? GetOriginControlData(Guid actorId, Guid resourceId)
        {
            var d = ControlManagerDao.GetControlData(this.category.code, actorId, resourceId);
            return d;
        }

        /// <summary>
        /// 强制将权限值更新到数据
        /// </summary>
        /// <param name="actorKey"></param>
        /// <param name="resourceId"></param>
        /// <param name="operationsCode"></param>
        /// <returns></returns>
        public bool AddOrEditControlData(Guid actorKey, Guid resourceId, params int[] operationsCode)
        {
            var controlData = CombinePermissionCode(operationsCode);
            //if (controlData == 0)
            //    return RemoveControlData(actorKey, resourceId);
            return ControlManagerDao.AddOrEditControlData(this.category.code, actorKey, resourceId, controlData);
        }
    }
}